/*
 * xmega.c
 *
 * Created: 25.01.2014 20:44:59
 *  Author: Vladislav
 */ 


#include "xmega.h"

void USARTDinit (void);
void USARTEinit (void);
void RTCinit (void);
void SPIinit(void);
void I_8_32(void);
void tc0_disable(TC0_t *ptc);
void tc1_disable(TC1_t *ptc);
void ClockTickStart(void);
void SystemClocksInit(void);
void USARTC0Init(void);
void USARTD0Init(void);
void XMEGAinit(void);
void PORTSinit(void);

void USARTEinit (void) // for VFD
{
	USARTE0.BAUDCTRLA=0x67; //0xb; // 11d
	USARTE0.BAUDCTRLB=0; //0xf0; // BSCALE=-1 // 19.2 KBod
	USARTE0.CTRLC=0x23; //USART_CHSIZE_8BIT_gc | USART_PMODE_EVEN_gc | false;
	PORTE.OUTSET=8;
	PORTE.DIRSET=8;
	PORTE_PIN3CTRL=PORT_INVEN_bm; //0x40;
	USARTE0.CTRLB |= 8; // USART_TXEN_bm;
}

void USARTDinit (void) // for VFD
{
	PORTD_OUTSET=1; // OE - passive
	PORTD_DIRSET=0xb; // out - ss, sck, mosi
	USARTD0_CTRLC=USART_CMODE_MSPI_gc|2; //0xc2; // mode 3,data order 0, phase 1
	USARTD0_BAUDCTRLA=1; //2 MHz/4=500 KHz ~ 16mks per byte
	USARTD0_BAUDCTRLB=0; //2 MHz/4=500 KHz ~ 16mks per byte
	PORTD_PIN1CTRL=PORT_INVEN_bm; //0x40 - bit 6 inventing
	USARTD0_CTRLB=USART_TXEN_bm; // Tx enable only- 8
}


void RTCinit (void)
{
	RTC_PER=0xffff; // full period
	OSC_CTRL|=OSC_RC32KEN_bm; // RC32KEN
	CLK_RTCCTRL=CLK_RTCSRC1_bm|CLK_RTCEN_bm; // 5;
	RTC_CTRL|=RTC_PRESCALER_DIV1_gc; // 1 - divide on 1
}



void I_8_32(void)
{
	OSC.XOSCCTRL = 0x4B; // external osc. 2-9MHz; start after 16 000 CLK
	OSC.CTRL = OSC_XOSCEN_bm; // external osc. enable (0x08)
	while(!(OSC.STATUS & OSC_XOSCRDY_bm)) ; // waite stabylyty external osc.
	OSC.PLLCTRL = 0xC4; // external source, *4
	OSC.CTRL |=  OSC_PLLEN_bm; // PLL enable (0x10)
	while(!(OSC.STATUS & OSC_PLLRDY_bm)) ; // PLL is ready
	CCP = CCP_IOREG_gc; //Security Signature to modify clock (0xD8)
	CLK.CTRL = 0x04; // PLL select
	OSC.CTRL &= ~OSC_RC2MEN_bm; // internal 2 MHz disable (0xFE)
}

void SPIinit(void)
{
	SPIC.CTRL = SPI_ENABLE_bm | SPI_MASTER_bm | SPI_PRESCALER_DIV4_gc;//0x50
	SPIC.INTCTRL=(SPIC.INTCTRL & (~SPI_INTLVL_gm)) | SPI_INTLVL_OFF_gc;
}


void tc0_disable(TC0_t *ptc)
{
	// Timer/Counter off
	ptc->CTRLA=(ptc->CTRLA & (~TC0_CLKSEL_gm)) | TC_CLKSEL_OFF_gc;
	// Issue a reset command
	ptc->CTRLFSET=TC_CMD_RESET_gc;
} // tc0_disable()

void tc1_disable(TC1_t *ptc)
{
	// Timer/Counter off
	ptc->CTRLA=(ptc->CTRLA & (~TC1_CLKSEL_gm)) | TC_CLKSEL_OFF_gc;
	// Issue a reset command
	ptc->CTRLFSET=TC_CMD_RESET_gc;
} //


void ClockTickStart(void)
{
	// Local variables
	unsigned char s;
	uint32_t  clk_per_freq;
	uint32_t  period;
	// Save interrupts enabled/disabled state
	s=SREG;
	// Disable interrupts
	asm("cli");
	// Disable and reset the timer/counter just to be sure
	tc1_disable(&TCC1);
	// Clock source: Peripheral Clock/1
	TCC1.CTRLA=(TCC1.CTRLA & (~TC1_CLKSEL_gm)) | TC_CLKSEL_DIV1_gc;
	// Mode: Normal Operation, Overflow Int./Event on TOP
	// Compare/Capture on channel A: Off
	// Compare/Capture on channel B: Off
	TCC1.CTRLB=(TCC1.CTRLB & (~(TC1_CCAEN_bm | TC1_CCBEN_bm | TC1_WGMODE_gm))) |
	TC_WGMODE_NORMAL_gc;
	// Capture event source: None
	// Capture event action: None
	TCC1.CTRLD=(TCC1.CTRLD & (~(TC1_EVACT_gm | TC1_EVSEL_gm))) |
	TC_EVACT_OFF_gc | TC_EVSEL_OFF_gc;
	// Overflow interrupt: High Level
	// Error interrupt: Disabled
	TCC1.INTCTRLA=(TCC1.INTCTRLA & (~(TC1_ERRINTLVL_gm | TC1_OVFINTLVL_gm))) |
	TC_ERRINTLVL_OFF_gc | TC_OVFINTLVL_HI_gc;
	// Compare/Capture channel A interrupt: Disabled
	// Compare/Capture channel B interrupt: Disabled
	TCC1.INTCTRLB=(TCC1.INTCTRLB & (~(TC1_CCBINTLVL_gm | TC1_CCAINTLVL_gm))) |
	TC_CCBINTLVL_OFF_gc | TC_CCAINTLVL_OFF_gc;
	// High resolution extension: Off
	HIRESC.CTRLA&= ~HIRES_HREN1_bm;
	// Clear the interrupt flags
	TCC1.INTFLAGS=TCC1.INTFLAGS;
	// Set counter register
	TCC1.CNT=0x0000;
	// Calculate period
	// Note: The following equation to calculate the period assumes prescaler=CLK/1
	clk_per_freq   =  F_CPU;
	period         =  (uint32_t)(((2 * clk_per_freq) + (1 * 2 * (uint32_t)OS_TICKS_PER_SEC))
	/             ((1 * 2 * (uint32_t)OS_TICKS_PER_SEC)));
	// Set timer period register (maximum value=(2^16)-1=65535)
	TCC1.PER=period;
	// Set channel A Compare/Capture register
	TCC1.CCA=0x0000;
	// Set channel B Compare/Capture register
	TCC1.CCB=0x0000;
	// Restore interrupts enabled/disabled state
	SREG=s;
} // ClockTickStart()

// System clocks initialization
void SystemClocksInit(void)
{
	
	unsigned char n,s;

	// Optimize for speed
	//#pragma optsize-
	// Save interrupts enabled/disabled state
	s=SREG;
	// Disable interrupts
	asm("cli");

	// External 8000,000 kHz oscillator initialization
	// Crystal oscillator increased drive current: Off
	// External Clock Source - Startup Time: 0.4-16 MHz Quartz Crystal - 16k CLK
	OSC.XOSCCTRL=OSC_FRQRANGE_2TO9_gc | OSC_XOSCSEL_XTAL_16KCLK_gc;
	// Enable the external oscillator/clock source
	OSC.CTRL|=OSC_XOSCEN_bm;

	// Wait for the external oscillator to stabilize
	while ((OSC.STATUS & OSC_XOSCRDY_bm)==0);

	// PLL initialization
	// PLL clock source: External Osc. or Clock
	// PLL multiplication factor: 4
	// PLL output/2: Off
	// PLL frequency: 32,000000 MHz
	// Set the PLL clock source and multiplication factor
	n=(OSC.PLLCTRL & (~(OSC_PLLSRC_gm | OSC_PLLDIV_bm | OSC_PLLFAC_gm))) |
	OSC_PLLSRC_XOSC_gc | (0<<OSC_PLLDIV_bp) | 4;
	CCP=CCP_IOREG_gc;
	OSC.PLLCTRL=n;
	// Enable the PLL
	OSC.CTRL|=OSC_PLLEN_bm;

	// System Clock prescaler A division factor: 1
	// System Clock prescalers B & C division factors: B:1, C:1
	// ClkPer4: 32000,000 kHz
	// ClkPer2: 32000,000 kHz
	// ClkPer:  32000,000 kHz
	// ClkCPU:  32000,000 kHz
	n=(CLK.PSCTRL & (~(CLK_PSADIV_gm | CLK_PSBCDIV1_bm | CLK_PSBCDIV0_bm))) |
	CLK_PSADIV_1_gc | CLK_PSBCDIV_1_1_gc;
	CCP=CCP_IOREG_gc;
	CLK.PSCTRL=n;

	// Wait for the PLL to stabilize
	while ((OSC.STATUS & OSC_PLLRDY_bm)==0);

	// Select the system clock source: Phase Locked Loop
	n=(CLK.CTRL & (~CLK_SCLKSEL_gm)) | CLK_SCLKSEL_PLL_gc;
	CCP=CCP_IOREG_gc;
	CLK.CTRL=n;

	// Disable the unused oscillators: 2 MHz, 32 MHz, internal 32 kHz
	OSC.CTRL&= ~(OSC_RC2MEN_bm | OSC_RC32MEN_bm | OSC_RC32KEN_bm);

	// ClkPer output disabled
	PORTCFG.CLKEVOUT&= ~(PORTCFG_CLKOUTSEL_gm | PORTCFG_CLKOUT_gm);
	// Restore interrupts enabled/disabled state
	SREG=s;
	// Restore optimization for size if needed

} // SystemClocksInit()


void USARTC0Init(void)
{
	// Note: The correct PORTC direction for the RxD, TxD and XCK signals
	// is configured in the PortsInit function

	// Transmitter is enabled
	// Set TxD=1
	PORTC.OUTSET=0x08;

	// Communication mode: Asynchronous USART
	// Data bits: 8
	// Stop bits: 1
	// Parity: Disabled
	USARTC0.CTRLC=USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | USART_CHSIZE_8BIT_gc;

	// Receive complete interrupt: High Level
	// Transmit complete interrupt: Disabled
	// Data register empty interrupt: Disabled
	USARTC0.CTRLA=(USARTC0.CTRLA & (~(USART_RXCINTLVL_gm | USART_TXCINTLVL_gm | USART_DREINTLVL_gm))) |
	USART_RXCINTLVL_HI_gc | USART_TXCINTLVL_OFF_gc | USART_DREINTLVL_OFF_gc;

	
	// Required Baud rate: 9600
	// Real Baud Rate: 9601.0 (x2 Mode), Error: 0.0 %
	USARTC0.BAUDCTRLA=0x85;
	USARTC0.BAUDCTRLB=((0x09 << USART_BSCALE_bp) & USART_BSCALE_gm) | 0x0C;

	// Receiver: On
	// Transmitter: On
	// Double transmission speed mode: On
	// Multi-processor communication mode: Off
	USARTC0.CTRLB=(USARTC0.CTRLB & (~(USART_RXEN_bm | USART_TXEN_bm | USART_CLK2X_bm | USART_MPCM_bm | USART_TXB8_bm))) |
	USART_RXEN_bm | USART_TXEN_bm | USART_CLK2X_bm;

	
} // USARTC0Init()



void USARTD0Init(void)
{
	// Note: the correct PORTD direction for the RxD, TxD and XCK signals
	// is configured in the PortsInit function

	// Transmitter is enabled
	// Set TxD=1
	PORTD.OUTSET=0x08;

	// Communication mode: Asynchronous USART
	// Data bits: 8
	// Stop bits: 1
	// Parity: Disabled
	USARTD0.CTRLC=USART_CMODE_ASYNCHRONOUS_gc | USART_PMODE_DISABLED_gc | USART_CHSIZE_8BIT_gc;

	// Receive complete interrupt: High Level
	// Transmit complete interrupt: Disabled
	// Data register empty interrupt: Disabled
	USARTD0.CTRLA=(USARTD0.CTRLA & (~(USART_RXCINTLVL_gm | USART_TXCINTLVL_gm | USART_DREINTLVL_gm))) |
	USART_RXCINTLVL_HI_gc | USART_TXCINTLVL_OFF_gc | USART_DREINTLVL_OFF_gc;

	
	
	// Required Baud rate: 9600
	// Real Baud Rate: 9601.0 (x1 Mode), Error: 0.0 %
	USARTD0.BAUDCTRLA=0xF5;
	USARTD0.BAUDCTRLB=((0x0C << USART_BSCALE_bp) & USART_BSCALE_gm) | 0x0C;

	// Receiver: On
	// Transmitter: On
	// Double transmission speed mode: Off
	// Multi-processor communication mode: Off
	USARTD0.CTRLB=(USARTD0.CTRLB & (~(USART_RXEN_bm | USART_TXEN_bm | USART_CLK2X_bm | USART_MPCM_bm | USART_TXB8_bm))) |
	USART_RXEN_bm | USART_TXEN_bm;

} // USARTC0Init()



void XMEGAinit(void)
{
	// Local variables
	unsigned char n;
	// Interrupt system initialization
	// Make sure the interrupts are disabled
	asm("cli");
	//Low level interrupt: On
	//Round-robin scheduling for low level interrupt: Off
	//Medium level interrupt: On
	//High level interrupt: On
	//The interrupt vectors will be placed at the start of the Application FLASH section
	n=(PMIC.CTRL & (~(PMIC_RREN_bm | PMIC_IVSEL_bm | PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm))) |
	PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm;
	CCP=CCP_IOREG_gc;
	PMIC.CTRL=n;
	// Set the default priority for round-robin scheduling
	PMIC.INTPRI=0x00;
	//Setup XMEGA peripherals
	SystemClocksInit();
	PORTSinit();
	USARTDinit();
	USARTEinit();
	SPIinit();
	//asm("sei");
	
} // AVRInit()



void PORTSinit()
{
	
	PORTA.DIRCLR=PIN2_bm|PIN1_bm;

	PORTC.DIRSET=PIN5_bm|PIN7_bm|PIN4_bm;
	PORTC.OUTSET=PIN4_bm;
	
	
	
	PORTB.OUTCLR=PIN2_bm; // hard reset CAN - active
	PORTB.DIRSET=PIN2_bm;
	PORTB.OUTSET=PIN2_bm; // hard reset CAN - passive
	PORTB.DIRCLR = PIN3_bm;
	PORTB.PIN3CTRL = PORT_ISC_FALLING_gc | PORT_OPC_PULLUP_gc;
	PORTB.INT0MASK = PIN3_bm;
	PORTB.INTCTRL = PORT_INT0LVL_HI_gc;
	PORTB.INTFLAGS = 0x00;
	
	//PORTA.DIRCLR = PIN5_bm;
	//PORTA.INT0MASK = PIN5_bm;
	//PORTA.PIN5CTRL =  PORT_ISC_FALLING_gc | PORT_OPC_PULLUP_gc;
	//PORTA.INTCTRL = PORT_INT0LVL_LO_gc;
	//PORTA.INTFLAGS = 0x00;
	

	PORTD.OUTSET=0x10; // ss passive
	PORTD.DIRSET=0xb0;
	SPID.CTRL=0x50;
	
	
	
	
	
}